#include "layer.h"

/* ------------------------------ */
/* ----------------------------- */

Layer::~Layer() {
  int j,k;
  delete agrid; 
  if(grid1d) delete [] grid1d;
  if(grid2d) {
    for(j=0;j<ynum;j++) delete [] grid2d[j];
    delete [] grid2d;
  }
  if(grid3d) {
    for(j=0;j<ynum;j++)
      for(k=0;k<tnum;k++) delete [] grid3d[j][k];
    for(j=0;j<ynum;j++)  delete [] grid3d[j];
    delete [] grid3d;
  }
}

/* ----------------------------- */
/* ---------------------------- */

void Layer::set(int xnum_inp,int ynum_inp,int tnum_inp,double length_inp,double width_inp,double time_length_inp,
		double doping_lhs_inp,double doping_rhs_inp,double perx_lhs_inp,double perx_rhs_inp,
		double pery_lhs_inp,double pery_rhs_inp,double bias_inp,
		int traps,double barrier, char * input_file, double Pz_fraction, double Psp_fraction, int fluc_test, 
		double fluct_perc ) {

  int i,j,k;
  double tmp_alloy_x,tmp_alloy_y,tmp_doping;
  double * dpx, * dpy;

  xnum 	= xnum_inp;
  ynum 	= ynum_inp;
  tnum	= tnum_inp;
  Temperature =	300.0;
  doping_lhs = doping_lhs_inp;
  doping_rhs = doping_rhs_inp;
  lhs_alloy_x = perx_lhs_inp;
  rhs_alloy_x = perx_rhs_inp;
  lhs_alloy_y = pery_lhs_inp;
  rhs_alloy_y = pery_rhs_inp;
  bias = bias_inp;
  dx = length_inp;
  dy =	width_inp;
  dt = time_length_inp;

  agrid = new Alloy_var (input_file,Pz_fraction,Psp_fraction);
  if(!traps) agrid->notraps();

  if(xnum<1) nrerror("Layer with bad x-dimension");
  if(ynum==1 && tnum==0) {
    grid1d = new Phys_var [xnum];
    grid2d = 0;
    grid3d = 0;
    if(grid1d==NULL) nrerror("memory allocation failure for grid1d in Layer::set");
    if(fluc_test ) {
      if(rhs_alloy_x>0 || lhs_alloy_x>0) dpx = fluctuation(fluc_test-1, xnum,0.5*(rhs_alloy_x+lhs_alloy_x),fluct_perc);
      else dpx = fluctuation(fluc_test-1, xnum,0.5*(rhs_alloy_x+lhs_alloy_x),0);
      if(rhs_alloy_y>0 || lhs_alloy_y>0) dpy = fluctuation(fluc_test-1, xnum,0.5*(rhs_alloy_y+lhs_alloy_y),fluct_perc);
      else dpy = fluctuation(fluc_test-1, xnum,0.5*(rhs_alloy_y+lhs_alloy_y),0);
      for(i=0;i<xnum;i++) {
	tmp_doping = doping_lhs + (doping_rhs-doping_lhs)*( (double)i/(double)(xnum-1) );
	grid1d[i].set(dx/(double)xnum,0,0,dpx[i],dpy[i],tmp_doping,bias-barrier,agrid,0,0);
      }
      delete [] dpx;
      delete [] dpy;
    }
    else {
      for(i=0;i<xnum;i++) {
	tmp_alloy_x = lhs_alloy_x + (rhs_alloy_x-lhs_alloy_x)*( (double)i/(double)(xnum-1) );
	tmp_alloy_y = lhs_alloy_y + (rhs_alloy_y-lhs_alloy_y)*( (double)i/(double)(xnum-1) );
	tmp_doping = doping_lhs + (doping_rhs-doping_lhs)*( (double)i/(double)(xnum-1) );
	grid1d[i].set(dx/(double)xnum,0,0,tmp_alloy_x,tmp_alloy_y,tmp_doping,bias-barrier,agrid,0,0);
      }
    }
    
  }
  else if(ynum>1 && tnum==0) {
    grid1d = 0;
    grid2d = new Phys_var * [xnum];
    grid3d = 0;
    if(grid2d==NULL) nrerror("memory allocation failure for grid2d in Layer::set");
    for(i=0;i<xnum;i++) {
      grid2d[i] = new Phys_var [ynum];
      if(grid2d[i]==NULL) nrerror("memory allocation failure for grid2d[i] in Layer::set");
    }
    for(i=0;i<xnum;i++) {
      tmp_alloy_x = lhs_alloy_x + (rhs_alloy_x-lhs_alloy_x)*( (double)i/(double)(xnum-1) );
      tmp_alloy_y = lhs_alloy_y + (rhs_alloy_y-lhs_alloy_y)*( (double)i/(double)(xnum-1) );
      tmp_doping = doping_lhs + (doping_rhs-doping_lhs)*( (double)i/(double)(xnum-1) );
      for(j=0;j<ynum;j++) grid2d[i][j].set(dx/(double)xnum,dy/(double)ynum,0,tmp_alloy_x,tmp_alloy_y,
					   tmp_doping,bias-barrier,agrid,0,0);
    }
  }
  else if(ynum==1 && tnum>0) {
    grid1d = 0;
    grid2d = new Phys_var * [xnum];
    grid3d = 0;
    for(i=0;i<xnum;i++) grid2d[i] = new Phys_var [tnum];
    for(i=0;i<xnum;i++) {
      tmp_alloy_x = lhs_alloy_x + (rhs_alloy_x-lhs_alloy_x)*( (double)i/(double)(xnum-1) );
      tmp_alloy_y = lhs_alloy_y + (rhs_alloy_y-lhs_alloy_y)*( (double)i/(double)(xnum-1) );
      tmp_doping = doping_lhs + (doping_rhs-doping_lhs)*( (double)i/(double)(xnum-1) );
      for(j=0;j<tnum;j++) grid2d[i][j].set(dx/(double)xnum,0,dt/(double)tnum,tmp_alloy_x,tmp_alloy_y,
					   tmp_doping,bias-barrier,agrid,0,0);
    }
  }
  else if(ynum>1 && tnum>0) {
    grid1d = 0;
    grid2d = 0;
    grid3d = new Phys_var ** [xnum];
    if(grid3d==NULL) nrerror("memory allocation failure for grid3d in Layer::set");
    for(i=0;i<xnum;i++) {
      grid3d[i] = new Phys_var * [ynum];
      if(grid3d[i]==NULL) nrerror("memory allocation failure for grid3d[] in Layer::set");
    }
    for(i=0;i<xnum;i++) 
      for(j=0;j<ynum;j++) {
	grid3d[i][j] = new Phys_var [tnum];
	if(grid3d[i][j]==NULL) nrerror("memory allocation failure for grid3d[][] in Layer::set");
      }
    for(i=0;i<xnum;i++) {
      tmp_alloy_x = lhs_alloy_x + (rhs_alloy_x-lhs_alloy_x)*( (double)i/(double)(xnum-1) );
      tmp_alloy_y = lhs_alloy_y + (rhs_alloy_y-lhs_alloy_y)*( (double)i/(double)(xnum-1) );
      tmp_doping = doping_lhs + (doping_rhs-doping_lhs)*( (double)i/(double)(xnum-1) );
      for(j=0;j<ynum;j++)
	for(k=0;k<tnum;k++) grid3d[i][j][k].set(dx/(double)xnum,dy/(double)ynum,dt/(double)tnum,
						tmp_alloy_x,tmp_alloy_y,tmp_doping,bias-barrier,agrid,0,0);
    }
  }
  else nrerror("Bad layer overall dimension. Check file ./INPUT_FILES/device.inp for errors");

	
}

/* ---------------------------------------------------- */
/* ---------------------------------------------------- */

void Layer::bias_modify(double bias_inp	) {

  int i,j;

  bias = bias_inp;

  if(grid1d) for(i=0;i<xnum;i++) grid1d[i].set_potential(bias_inp);
  else if(grid2d) for(i=0;i<xnum;i++) for(j=0;i<ynum;j++) grid2d[i][j].set_potential(bias_inp);
  else  nrerror("memory allocation failure for grid1d in Device::bias_modify");
	
}
/* ---------------------------------------------------------------- */
/* ---------------------------------------------------------------- */

void Layer::show(double pos, FILE * fp1, FILE * fp2, FILE * fp3, FILE * fp4,
		 FILE * fp5, FILE * fp6,FILE * fp7, FILE * fp8, FILE * fp9 ) {

  int i,j;
  double posy,posx;

  if(grid1d) {

    for(i=0;i<xnum;i++) {
      
      pos += grid1d[i].xsize();
      
      fprintf(fp1,"%le  ",pos);
      grid1d[i].show_band( fp1);
      fprintf(fp1,"\n");
      
      fprintf(fp2,"%le  ",pos);
      grid1d[i].show_carrier( fp2);
      fprintf(fp2,"\n");
      
      fprintf(fp3,"%le  ",pos);
      grid1d[i].show_potential( fp3 );
      fprintf(fp3,"\n");
      
      fprintf(fp4,"%le  ",pos);
      grid1d[i].show_current( fp4 );
      fprintf(fp4,"\n");
      
      fprintf(fp5,"%le  ",pos);
      grid1d[i].show_well_e( fp5 );
      fprintf(fp5,"\n");
      
      fprintf(fp6,"%le  ",pos);
      grid1d[i].show_well_h( fp6 );
      fprintf(fp6,"\n");
      
      fprintf(fp7,"%le  ",pos);
      grid1d[i].show_lev_e( fp7 );
      fprintf(fp7,"\n");
      
      fprintf(fp8,"%le  ",pos);
      grid1d[i].show_lev_h( fp8 );
      fprintf(fp8,"\n");

      fprintf(fp9,"%le  ",pos);
      grid1d[i].show_optical_bandgap( fp9 );
      fprintf(fp9,"\n");
      
    }

  }
  else if(grid2d) {

    posy = 0;
    posx = pos;
    for(j=0;j<ynum;j++) {
      posy += grid2d[0][j].ysize();
      pos = posx;
      for(i=0;i<xnum;i++) {

	pos += grid2d[i][j].xsize();

	fprintf(fp1,"%le  %le  ",pos,posy);
	grid2d[i][j].show_band( fp1);
	fprintf(fp1,"\n");

	fprintf(fp2,"%le  %le  ",pos,posy);
	grid2d[i][j].show_carrier( fp2);
	fprintf(fp2,"\n");

	fprintf(fp3,"%le  %le  ",pos,posy);
	grid2d[i][j].show_potential( fp3 );
	fprintf(fp3,"\n");

	fprintf(fp4,"%le  %le  ",pos,posy);
	grid2d[i][j].show_current( fp4 );
	fprintf(fp4,"\n");

	fprintf(fp5,"%le  %le  ",pos,posy);
	grid2d[i][j].show_well_e( fp5 );
	fprintf(fp5,"\n");

	fprintf(fp6,"%le  %le  ",pos,posy);
	grid2d[i][j].show_well_h( fp6 );
	fprintf(fp6,"\n");
	
	fprintf(fp7,"%le  %le  ",pos,posy);
	grid2d[i][j].show_lev_e( fp7 );
	fprintf(fp7,"\n");

	fprintf(fp8,"%le  %le  ",pos,posy);
	grid2d[i][j].show_lev_h( fp8 );
	fprintf(fp8,"\n");

	fprintf(fp9,"%le  ",pos);
	grid1d[i].show_optical_bandgap( fp9 );
	fprintf(fp9,"\n");
      
	
      }

      fprintf(fp1,"\n");
      fprintf(fp2,"\n");
      fprintf(fp3,"\n");
      fprintf(fp4,"\n");
      fprintf(fp5,"\n");
      fprintf(fp6,"\n");
      fprintf(fp7,"\n");
      fprintf(fp8,"\n");
      fprintf(fp9,"\n");
      
    }
    fprintf(fp1,"\n");
    fprintf(fp2,"\n");
    fprintf(fp3,"\n");
    fprintf(fp4,"\n");
    fprintf(fp5,"\n");
    fprintf(fp6,"\n");
    fprintf(fp7,"\n");
    fprintf(fp8,"\n");
    fprintf(fp9,"\n");
  }

}
